package org.kiwi.util;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * @email jack.liu.19910921@gmail.com
 * Created by jack on 17/7/28.
 */
public class ThreeDesUtil {

    public static final String DEFAULT_KEY = "11223f588810303828257951cbdd556677297398303036e2";

    public static final String VERIFY_KEY = "22113f588821303828257951cbdd556677297398313136e2";

    public static final String NXY_KEY = "336772973983f58882113136e51cbdd55622211038282579";

    /**
     * 在java中调用sun公司提供的3DES加密解密算法时,需要使用$JAVA_HOME/jre/lib/目录下如下的4个jar包
     * jce.jar security/US_export_policy.jar security/local_policy.jar ext/sunjce_provider.jar
     */
    private static final String ALGORITHM = "DESede"; // 定义 加密算法

    private static final String DEFAULT_CHARSET = "utf-8";

    private static final String HEX_STR = "0123456789abcdef";//小写十六进制字符

    /**
     * 3DES加密
     * keyByte 加密密钥,长度为24字节
     * src 加密的数据缓冲区(源)
     */
    public static byte[] encryptMode(byte[] keyByte, byte[] src) {
        try {
            // 生成密钥
            SecretKey desKey = new SecretKeySpec(keyByte, ALGORITHM);
            // 加密
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, desKey);
            return cipher.doFinal(src);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 3DES解密
     * keyByte 加密密钥,长度为24字节
     * src 加密后的缓冲区
     */
    public static byte[] decryptMode(byte[] keyByte, byte[] src) {
        try {
            // 生成密钥
            SecretKey desKey = new SecretKeySpec(keyByte, ALGORITHM);
            // 解密
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, desKey);
            return cipher.doFinal(src);
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 将十六进制字符串转换为字节数组
     */
    public static byte[] hexString2Binary(String hexString) {
        // hexString的长度对2取整,作为bytes的长度
        int len = hexString.length() / 2;
        byte[] bytes = new byte[len];
        byte high;// 字节高四位
        byte low;// 字节低四位
        for (int i = 0; i < len; i++) {
            // 右移四位得到高位
            high = (byte) ((HEX_STR.indexOf(hexString.charAt(2 * i))) << 4);
            low = (byte) HEX_STR.indexOf(hexString.charAt(2 * i + 1));
            bytes[i] = (byte) (high | low);// 高位做或运算
        }
        return bytes;
    }

    /**
     * 将字节数组转换为十六进制字符串输出
     */
    public static String binary2HexString(byte[] bytes) {
        String result = "";
        String hex;
        for (int i = 0; i < bytes.length; i++) {
            // 字节高4位
            hex = String.valueOf(HEX_STR.charAt((bytes[i] & 0xF0) >> 4));
            // 字节低4位
            hex += String.valueOf(HEX_STR.charAt(bytes[i] & 0x0F));
            result += hex;
        }
        return result;
    }

    /**
     * 将十六进制字符串转换成字节数组
     */
    public static byte[] hex2Byte(String str) {
        if (str == null) {
            return null;
        }
        str = str.trim();
        int len = str.length();
        if ((len == 0) || (len % 2 == 1))
            return null;
        byte[] b = new byte[len / 2];
        try {
            for (int i = 0; i < str.length(); i += 2) {
                b[(i / 2)] = (byte) Integer.decode("0x" + str.substring(i, i + 2)).intValue();
            }
            return b;
        } catch (Exception e) {

        }
        return null;
    }

    /**
     * 将字节数组转换成十六进制字符串
     */
    public static String byte2Hex(byte[] b) {
        StringBuffer sb = new StringBuffer(b.length);
        String temp;
        int len = b.length;
        for (int n = 0; n < len; n++) {
            temp = Integer.toHexString(b[n] & 0xFF);
            if (temp.length() == 1)
                sb = sb.append("0").append(temp);
            else {
                sb = sb.append(temp);
            }
        }
        return String.valueOf(sb);
    }

    public static String encrypt(String src) throws Exception {
        byte[] encoded = encryptMode(hexString2Binary(ThreeDesUtil.DEFAULT_KEY), src.getBytes(DEFAULT_CHARSET));
        return binary2HexString(encoded);
    }

    public static String decrypt(String src) throws Exception {
        byte[] decoded = decryptMode(hexString2Binary(ThreeDesUtil.DEFAULT_KEY), hexString2Binary(src));
        return new String(decoded, DEFAULT_CHARSET);
    }

    public static String encrypt(String src, String key) throws Exception {
        byte[] encoded = encryptMode(hexString2Binary(key), src.getBytes(DEFAULT_CHARSET));
        return binary2HexString(encoded);
    }

    public static String decrypt(String src, String key) throws Exception {
        byte[] decoded = decryptMode(hexString2Binary(key), hexString2Binary(src));
        return new String(decoded, DEFAULT_CHARSET);
    }
}
